#include "TutPDF.h"
#include <QDebug>

namespace Tutorial4
{
	/**
	* Constructor
	*/
	TutPDF::TutPDF() :
		Interactable(),
		mPDF(),
		mTotalNumberOfPages(0),
		mCurrentPageNumber(1),
		mPage(),
		mPages(),
		mPageSize(1,1),
		mLoadingTexture(),
		mFetchSize(false)
	{
		Interactable::setRotateable(false);
	}

	/**
	* Destructor
	*/
	TutPDF::~TutPDF()
	{
	}

	/**
	* Loads the PDF and starts caching sub processing in bg
	* \param inApplicationDirectory Path to the applications data directory
	* \param inFilePath Path to the PDF file
	*/
	bool TutPDF::load(const QString& inApplicationDirectory, const QString& inFilePath)
	{
		// load the pdf at 150dpi
		mPDF.load(inFilePath, 150);

		// obtain the total number of pages in the pdf
		mTotalNumberOfPages = mPDF.getNumPages();

		if(mTotalNumberOfPages < 1)
			return false;

		// load the display page with loading screen graphics
		bool success = mLoadingTexture.load(inApplicationDirectory+"loading.png");
		mPageSize = QVector2D(0.7f, 1.0f);

		return success;
	}

	/**
	* unload all initialized resources
	*/
	void TutPDF::unload()
	{
		mCurrentPageNumber = 1;
		mTotalNumberOfPages = 0;
		mPDF.unload();
		mPage.unload();
		mPages.clear();
		mLoadingTexture.unload();
	}

	/**
	* onUpdate event handler
	* \param inFrameTime elapsed time in seconds since the last frame
	*/
	void TutPDF::onUpdate(float inFrameTime)
	{
		// update the interactable parent class parameters
		Interactable::update(inFrameTime);

		int currentNumberOfPages = static_cast<int>(mPages.size());

		// check for newly cached pages
		if(currentNumberOfPages < mTotalNumberOfPages)
		{
			// if the number of cached pages in the pdf object is greater then the internal counter
			// then a new page has been cached. Update the internal map for the cached pages
			if(mPDF.getNumCachedPages() > currentNumberOfPages)
			{
				// New cached page available
				// update the internal cached pages list
				QVector<QString> cachedPages = mPDF.getPages();
				int pageNr = 1;
				foreach(QString path, cachedPages)
				{
					// update the map for the particular page number
					onPageCached(pageNr++, path);
				}
			}
		}

		// set the position and scale of the display page with the parameters of the Interactable parent class
		// this provides the ability to move and scale the page
		mPage.setScale(Interactable::getScale());
		mPage.setPosition(Interactable::getPosition());
	}

	/**
	* Draw the page
	*/
	void TutPDF::onRender()
	{
		// render the page
		if(mPage.isLoaded())
		{
			// if its the first page then obtain the page size of the sprite
			if(mFetchSize)
			{
				mPageSize = QVector2D(float(mPage.getPixelWidth())/float(mPage.getPixelHeight()), 1.0f);
				mFetchSize = false;
			}
			mPage.render();
		}
		else
		{
			// render the loading screen if the page is not loaded yet
			QVector2D pageHalfSize = mPageSize* 0.5f * getScale();
			glEnable(GL_BLEND);
			glEnable(GL_TEXTURE_2D);
			glBindTexture(GL_TEXTURE_2D, mLoadingTexture.getID());
			glPushMatrix();
			glTranslatef(getPosition().x(), getPosition().y(), 0.0f);
			glBegin(GL_QUADS);
			glTexCoord2f(0, 1);
			glVertex2f(-pageHalfSize.x(), -pageHalfSize.y());
			glTexCoord2f(1, 1);
			glVertex2f(pageHalfSize.x(), -pageHalfSize.y());
			glTexCoord2f(1, 0);
			glVertex2f(pageHalfSize.x(), pageHalfSize.y());
			glTexCoord2f(0, 0);
			glVertex2f(-pageHalfSize.x(), pageHalfSize.y());
			glEnd();
			glPopMatrix();
			glDisable(GL_TEXTURE_2D);
			glDisable(GL_BLEND);
		}
	}

	/**
	* Finger down event handler
	* \param inData holds the touch information
	*/
	void TutPDF::onFingerDown(const TouchListener::TouchData& inData)
	{
		// pass the touch event to update the parent's class parameters
		Interactable::fingerDown(inData);
	}

	/**
	* Finger up event handler
	* \param inData holds the touch information
	*/
	void TutPDF::onFingerUp(const TouchListener::TouchData& inData)
	{
		// pass the touch event to update the parent's class parameters
		Interactable::fingerUp(inData);
	}

	/**
	* Finger update event handler
	* \param inData holds the touch information
	*/
	void TutPDF::onFingerUpdate(const TouchListener::TouchData& inData)
	{
		// pass the touch event to update the parent's class parameters
		Interactable::fingerUpdate(inData);
	}

	/**
	* Handles new page
	* \param inPageNr page number
	* \param inPagePath path to the cached page
	*/
	void TutPDF::onPageCached(int inPageNr, const QString& inPagePath)
	{
		mPages[inPageNr] = inPagePath;

		// if the cached page is the first page then load the page into the display
		if(mPages.size() == 1)
		{
			mPage.unload();
			mPage.load(inPagePath, 0, 0, true, false);
			mFetchSize = true;
		}
	}

	/**
	* loads the previous page
	*/
	void TutPDF::previousPage()
	{
		// if current page's texture is not loaded yet
		if(!mPage.isLoaded())
			return;

		int cachedCount = static_cast<int>(mPages.size());

		// if there are no cached pages yet then exit
		if(cachedCount == 0)
			return;

		--mCurrentPageNumber;

		// if the page number is less than one then loop back to the last page in the cached page list
		if(mCurrentPageNumber < 1)
			mCurrentPageNumber = cachedCount;

		mPage.unload();
		mPage.load(mPages[mCurrentPageNumber], 0, 0, true, false);
	}

	/**
	* loads the next page
	*/
	void TutPDF::nextPage()
	{
		// if current page's texture is not loaded yet
		if(!mPage.isLoaded())
			return;

		int cachedCount = static_cast<int>(mPages.size());

		// if there are no cached pages yet then exit
		if(cachedCount == 0)
			return;

		++mCurrentPageNumber;

		// if the page number is greater than the total cached pages then loop back to the first page in the cached page list
		if(mCurrentPageNumber > cachedCount)
			mCurrentPageNumber = 1;

		mPage.unload();
		mPage.load(mPages[mCurrentPageNumber], 0, 0, true, false);
	}

	/**
	* Resets the current page to first page of pdf
	*/
	void TutPDF::reset()
	{
		// if current page's texture is not loaded yet
		if(!mPage.isLoaded())
			return;

		Interactable::setVelocity(QVector2D());

		int cachedCount = static_cast<int>(mPages.size());

		// if there are no cached pages yet then exit
		if(cachedCount == 0)
			return;

		mCurrentPageNumber = 1;
		mPage.unload();
		mPage.load(mPages[mCurrentPageNumber], 0, 0, true, false);
	}
}
